﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Activities;

using Microsoft.Practices.Unity;

using ERPStore.Extensions;

namespace ERPStore.Indexers.Lucene.Services
{
	public class IndexBuilder
	{
		public IndexBuilder(ERPStore.Logging.ILogger logger
				, ERPStore.Services.ICacheService cacheService)
		{
			this.Logger = logger;
			this.Settings = GlobalConfiguration.Configuration.DependencyResolver.GetService<Models.Settings>();
			this.CacheService = cacheService;
		}

		protected ERPStore.Logging.ILogger Logger { get; private set; }
		protected Services.CatalogService LuceneCatalogService { get; private set; }
		protected Models.Settings Settings { get; private set; }
		protected ERPStore.Services.ICacheService CacheService { get; private set; }

		internal CloudSoft.Workflows.ProgressReporter LuceneIndexProgress
		{
			get
			{
				return CloudSoft.Workflows.ProgressReporterCollector.Get("LuceneIndexProgress");
			}
		}


		public void Start()
		{
			if (LuceneIndexProgress != null)
			{
				throw new Exception("already building index");
			}

			StartBuildIndex();
		}

		public void Stop()
		{
			if (LuceneIndexProgress != null)
			{
				LuceneIndexProgress.CancelRequested = true;
			}
		}

		public CloudSoft.Workflows.ProgressReporter GetCurrentWorker()
		{
			return LuceneIndexProgress;
		}

		private void StartBuildIndex()
		{
			var path = Settings.Path;
			string workingFolder = Guid.NewGuid().ToString().Replace("-","").Substring(0,8);

			var parameters = new Dictionary<string, object>();
			parameters.Add("PageSize", 100);
			parameters.Add("IndexPath", path);
			parameters.Add("WorkingFolder", workingFolder);

			var pg = CloudSoft.Workflows.ProgressReporterCollector.GetNew();
			pg.Id = "LuceneIndexProgress";

			CloudSoft.Workflows.WorkflowQueueUserWorkItem.RunAsync(
				new Workflows.BuildFullTextIndexWorkflow(),
				parameters,
				pg,
				(dic) =>
				{
					var targetFullPath = System.IO.Path.Combine(Settings.Path, "Catalog");
					var workingFullPath = System.IO.Path.Combine(Settings.Path, workingFolder);

					// Bascule sur le moteur de base
					TurnOffLuceneCatalogService();

					try
					{
						// Nettoyage du répertoire Catalog
						CleanUpCatalogFolder(targetFullPath);

						// Deplacement de l'index actuel ver le folder target
						MoveNewCatalog(workingFullPath, targetFullPath);

						// Bascule sur le moteur Lucene
						EnableLuceneCatalogService();
					}
					catch (Exception ex)
					{
						Logger.Error(ex);
					}
				},
				(ex) => 
				{ 
					Logger.Error(ex); 
				},
				() =>
				{
					if (LuceneIndexProgress != null)
					{
						LuceneIndexProgress.TerminatedDate = DateTime.Now;
					}
				}
			);
		}

		private void TurnOffLuceneCatalogService()
		{
			Logger.Info("Desactivation du moteur lucene");
			var connectorService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.IConnectorService>();
			connectorService.RegisterCatalogService();
		}

		private void CleanUpCatalogFolder(string fullPath)
		{
			var files = System.IO.Directory.GetFiles(fullPath, "*.*");
			foreach (var fileName in files)
			{
				System.IO.File.Delete(fileName);
			}
		}

		private void MoveNewCatalog(string workingPath, string targetPath)
		{
			var files = System.IO.Directory.GetFiles(workingPath, "*.*");
			foreach (var fileName in files)
			{
				var fileInfo = new System.IO.FileInfo(fileName);
				var targetFileName = System.IO.Path.Combine(targetPath, fileInfo.Name);

				System.IO.File.Copy(fileName, targetFileName);
				System.IO.File.Delete(fileName);
			}
			System.IO.Directory.Delete(workingPath);
		}

		public void EnableLuceneCatalogService()
		{
			var repository = GlobalConfiguration.Configuration.DependencyResolver.GetService<Repositories.LuceneRepository>();
			if (repository.IsEmpty())
			{
				return;
			}

			var connectorService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.IConnectorService>();

			connectorService.RegisterCatalogService();
			var catalogService = DependencyResolver.Current.GetService<ERPStore.Services.ICatalogService>();
			var analyzer = DependencyResolver.Current.GetService<global::Lucene.Net.Analysis.Analyzer>();

			var injectionMembers = new InjectionMember[] 
				{ 
					new InjectionConstructor(catalogService, Logger, analyzer, Settings, repository) ,
				};

			var container = GlobalConfiguration.Configuration.DependencyResolver.GetContainer();
			container.RegisterType<ERPStore.Services.ICatalogService, Services.CatalogService>(new TransientLifetimeManager(), injectionMembers);
			Logger.Warn("Activation du moteur lucene");
		}
	}
}
